// 认证状态管理模块
// @/store/modules/auth.ts

import { defineStore } from 'pinia'
import { ref, computed, watch } from 'vue'
import type {
  AuthState,
  UserInfo,
  AuthUserInfo,
  LoginParams,
  LoginResponse,
  MobileLoginParams,
  TokenInfo,
  AuthStorageKey
} from '@/types/auth'
import { AuthEvent, AuthErrorCode } from '@/types/auth'
import { AuthError } from '@/types/auth'
import { AuthStorageKey as StorageKey } from '@/types/auth'
import { http } from '../../utils/http'
import { HttpError } from '../../utils/http/HttpError'
import { EventBus } from '../../utils/eventBus'
import { StorageManager } from '../../utils/storage'
import { CryptoUtil } from '../../utils/crypto'

// API 接口定义
interface AuthAPI {
  login(params: LoginParams): Promise<LoginResponse>
  mobileLogin(params: MobileLoginParams): Promise<LoginResponse>
  logout(): Promise<void>
  refreshToken(refreshToken: string): Promise<TokenInfo>
  getUserInfo(): Promise<AuthUserInfo>
  getPermissions(): Promise<string[]>
}

// 认证 API 实现
class AuthService implements AuthAPI {
  async login(params: LoginParams): Promise<LoginResponse> {
    const response = await http.post<LoginResponse>('/api/auth/login', {
      ...params,
      password: CryptoUtil.hash(params.password) // 密码哈希传输
    }, {
      loading: '登录中...'
    })
    return response
  }

  async mobileLogin(params: MobileLoginParams): Promise<LoginResponse> {
    return http.post<LoginResponse>('/api/auth/mobile-login', params, {
      loading: '登录中...'
    })
  }

  async logout(): Promise<void> {
    return http.post('/api/auth/logout')
  }

  async refreshToken(refreshToken: string): Promise<TokenInfo> {
    return http.post<TokenInfo>('/api/auth/refresh-token', {
      refreshToken
    })
  }

  async getUserInfo(): Promise<AuthUserInfo> {
    return http.get<AuthUserInfo>('/api/auth/user-info', {}, {
      cache: true,
      cacheTime: 5 * 60 * 1000
    })
  }

  async getPermissions(): Promise<string[]> {
    return http.get<string[]>('/api/auth/permissions', {}, {
      cache: true,
      cacheTime: 10 * 60 * 1000
    })
  }
}

export const useAuthStore = defineStore('auth', () => {
  // 服务实例
  const authService = new AuthService()
  const storage = new StorageManager('auth')
  const eventBus = EventBus.getInstance()

  // 状态定义
  const token = ref<string | null>(null)
  const refreshToken = ref<string | null>(null)
  const tokenExpireTime = ref<number | null>(null)
  const userInfo = ref<AuthUserInfo | null>(null)
  const permissions = ref<string[]>([])
  const roles = ref<string[]>([])
  const rememberMe = ref<boolean>(false)
  const isRefreshing = ref<boolean>(false)
  const refreshPromise = ref<Promise<void> | null>(null)

  // 计算属性
  const isLoggedIn = computed(() => !!token.value && !!userInfo.value)
  
  const isTokenExpired = computed(() => {
    if (!tokenExpireTime.value) return false
    return Date.now() > tokenExpireTime.value
  })

  const isTokenNearExpiry = computed(() => {
    if (!tokenExpireTime.value) return false
    const fiveMinutes = 5 * 60 * 1000
    return Date.now() > tokenExpireTime.value - fiveMinutes
  })

  const hasPermission = computed(() => {
    return (permission: string): boolean => {
      if (!permissions.value.length) return false
      return permissions.value.includes(permission) || permissions.value.includes('*')
    }
  })

  const hasRole = computed(() => {
    return (role: string): boolean => {
      if (!roles.value.length) return false
      return roles.value.includes(role) || roles.value.includes('admin')
    }
  })

  const hasAnyPermission = computed(() => {
    return (...perms: string[]): boolean => {
      return perms.some(perm => hasPermission.value(perm))
    }
  })

  const hasAllPermissions = computed(() => {
    return (...perms: string[]): boolean => {
      return perms.every(perm => hasPermission.value(perm))
    }
  })

  // 初始化
  const initialize = async (): Promise<void> => {
    try {
      // 从存储中恢复状态
      await restoreAuthState()
      
      // 检查 token 是否过期
      if (isTokenExpired.value) {
        await handleTokenExpired()
      } else if (isTokenNearExpiry.value && refreshToken.value) {
        // Token 即将过期，自动刷新
        await refreshAccessToken()
      }
      
      // 如果有 token 但没有用户信息，尝试获取
      if (token.value && !userInfo.value) {
        await fetchUserInfo()
      }
    } catch (error) {
      console.error('认证初始化失败:', error)
      await clearAuthState()
    }
  }

  // 登录
  const login = async (params: LoginParams): Promise<void> => {
    try {
      const response = await authService.login(params)
      await handleLoginSuccess(response, params.rememberMe)
      
      eventBus.emit(AuthEvent.LOGIN, { user: userInfo.value })
    } catch (error) {
      if (error instanceof HttpError) {
        throw new AuthError(
          getLoginErrorMessage(error),
          AuthErrorCode.INVALID_CREDENTIALS
        )
      }
      throw error
    }
  }

  // 手机号登录
  const mobileLogin = async (params: MobileLoginParams): Promise<void> => {
    try {
      const response = await authService.mobileLogin(params)
      await handleLoginSuccess(response, true)
      
      eventBus.emit(AuthEvent.LOGIN, { user: userInfo.value })
    } catch (error) {
      if (error instanceof HttpError) {
        throw new AuthError(
          '验证码错误或已过期',
          AuthErrorCode.INVALID_CREDENTIALS
        )
      }
      throw error
    }
  }

  // 处理登录成功
  const handleLoginSuccess = async (
    response: LoginResponse,
    remember?: boolean
  ): Promise<void> => {
    // 设置 token
    setToken(response.accessToken)
    setRefreshToken(response.refreshToken || null)
    
    // 计算过期时间
    if (response.expiresIn) {
      const expireTime = Date.now() + response.expiresIn * 1000
      setTokenExpireTime(expireTime)
    } else if (response.expiresAt) {
      setTokenExpireTime(response.expiresAt)
    }
    
    // 设置用户信息
    setUserInfo(response.user)
    
    // 设置权限和角色
    if (response.user.permissions) {
      setPermissions(response.user.permissions)
    }
    if (response.user.roles) {
      setRoles(response.user.roles.map(r => r.code))
    }
    
    // 设置记住我
    setRememberMe(remember || false)
    
    // 持久化状态
    await saveAuthState()
    
    // 启动 token 自动刷新
    startTokenRefreshTimer()
  }

  // 登出
  const logout = async (silent = false): Promise<void> => {
    try {
      if (!silent && token.value) {
        await authService.logout()
      }
    } catch (error) {
      console.error('登出请求失败:', error)
    } finally {
      await clearAuthState()
      eventBus.emit(AuthEvent.LOGOUT)
      
      // 跳转到登录页
      uni.reLaunch({
        url: '/pages/login/login'
      })
    }
  }

  // 刷新 Token
  const refreshAccessToken = async (): Promise<void> => {
    if (isRefreshing.value) {
      return refreshPromise.value!
    }
    
    if (!refreshToken.value) {
      throw new AuthError('无刷新令牌', AuthErrorCode.REFRESH_TOKEN_EXPIRED)
    }
    
    isRefreshing.value = true
    refreshPromise.value = doRefreshToken()
    
    try {
      await refreshPromise.value
    } finally {
      isRefreshing.value = false
      refreshPromise.value = null
    }
  }

  // 执行 token 刷新
  const doRefreshToken = async (): Promise<void> => {
    try {
      const response = await authService.refreshToken(refreshToken.value!)
      
      setToken(response.accessToken)
      if (response.refreshToken) {
        setRefreshToken(response.refreshToken)
      }
      
      if (response.expiresIn) {
        const expireTime = Date.now() + response.expiresIn * 1000
        setTokenExpireTime(expireTime)
      }
      
      await saveAuthState()
      startTokenRefreshTimer()
      
      eventBus.emit(AuthEvent.TOKEN_REFRESH)
    } catch (error) {
      // Token 刷新失败，清理状态并跳转登录
      await clearAuthState()
      throw new AuthError('令牌刷新失败', AuthErrorCode.REFRESH_TOKEN_EXPIRED)
    }
  }

  // 获取用户信息
  const fetchUserInfo = async (): Promise<void> => {
    try {
      const [userInfoData, permissionsData] = await Promise.all([
        authService.getUserInfo(),
        authService.getPermissions()
      ])
      
      setUserInfo(userInfoData)
      setPermissions(permissionsData)
      
      if (userInfoData.roles) {
        setRoles(userInfoData.roles.map(r => r.code))
      }
      
      await saveAuthState()
      
      eventBus.emit(AuthEvent.USER_UPDATE, { user: userInfoData })
    } catch (error) {
      console.error('获取用户信息失败:', error)
      throw error
    }
  }

  // 更新用户信息
  const updateUserInfo = async (updates: Partial<UserInfo>): Promise<void> => {
    if (!userInfo.value) return
    
    const updatedInfo = { ...userInfo.value, ...updates }
    setUserInfo(updatedInfo)
    await saveAuthState()
    
    eventBus.emit(AuthEvent.USER_UPDATE, { user: updatedInfo })
  }

  // Token 自动刷新定时器
  let tokenRefreshTimer: number | null = null
  
  const startTokenRefreshTimer = (): void => {
    stopTokenRefreshTimer()
    
    if (!tokenExpireTime.value || !refreshToken.value) return
    
    // 在过期前 5 分钟刷新
    const refreshTime = tokenExpireTime.value - Date.now() - 5 * 60 * 1000
    
    if (refreshTime > 0) {
      tokenRefreshTimer = setTimeout(async () => {
        try {
          await refreshAccessToken()
        } catch (error) {
          console.error('自动刷新 token 失败:', error)
        }
      }, refreshTime) as unknown as number
    }
  }
  
  const stopTokenRefreshTimer = (): void => {
    if (tokenRefreshTimer) {
      clearTimeout(tokenRefreshTimer)
      tokenRefreshTimer = null
    }
  }

  // 处理 Token 过期
  const handleTokenExpired = async (): Promise<void> => {
    eventBus.emit(AuthEvent.TOKEN_EXPIRED)
    
    if (refreshToken.value) {
      try {
        await refreshAccessToken()
      } catch (error) {
        await logout(true)
      }
    } else {
      await logout(true)
    }
  }

  // 状态设置方法
  const setToken = (value: string | null): void => {
    token.value = value
  }

  const setRefreshToken = (value: string | null): void => {
    refreshToken.value = value
  }

  const setTokenExpireTime = (value: number | null): void => {
    tokenExpireTime.value = value
  }

  const setUserInfo = (value: AuthUserInfo | null): void => {
    userInfo.value = value
  }

  const setPermissions = (value: string[]): void => {
    permissions.value = value
    eventBus.emit(AuthEvent.PERMISSION_CHANGE, { permissions: value })
  }

  const setRoles = (value: string[]): void => {
    roles.value = value
  }

  const setRememberMe = (value: boolean): void => {
    rememberMe.value = value
  }

  // 持久化存储
  const saveAuthState = async (): Promise<void> => {
    const tasks: Promise<void>[] = []
    
    if (rememberMe.value) {
      // 记住登录状态，使用加密存储
      if (token.value) {
        tasks.push(storage.setSecure(StorageKey.TOKEN, token.value))
      }
      if (refreshToken.value) {
        tasks.push(storage.setSecure(StorageKey.REFRESH_TOKEN, refreshToken.value))
      }
      if (userInfo.value) {
        tasks.push(storage.set(StorageKey.USER_INFO, userInfo.value))
      }
      if (permissions.value.length) {
        tasks.push(storage.set(StorageKey.PERMISSIONS, permissions.value))
      }
      if (roles.value.length) {
        tasks.push(storage.set(StorageKey.ROLES, roles.value))
      }
      if (tokenExpireTime.value) {
        tasks.push(storage.set(StorageKey.TOKEN_EXPIRE_TIME, tokenExpireTime.value))
      }
    } else {
      // 不记住登录状态，仅保存到内存（会话存储）
      if (token.value) {
        tasks.push(storage.setSession(StorageKey.TOKEN, token.value))
      }
      if (refreshToken.value) {
        tasks.push(storage.setSession(StorageKey.REFRESH_TOKEN, refreshToken.value))
      }
    }
    
    tasks.push(storage.set(StorageKey.REMEMBER_ME, rememberMe.value))
    
    await Promise.all(tasks)
  }

  // 恢复认证状态
  const restoreAuthState = async (): Promise<void> => {
    const remember = await storage.get<boolean>(StorageKey.REMEMBER_ME)
    setRememberMe(remember || false)
    
    if (remember) {
      // 从持久化存储恢复
      const [
        storedToken,
        storedRefreshToken,
        storedUserInfo,
        storedPermissions,
        storedRoles,
        storedExpireTime
      ] = await Promise.all([
        storage.getSecure<string>(StorageKey.TOKEN),
        storage.getSecure<string>(StorageKey.REFRESH_TOKEN),
        storage.get<AuthUserInfo>(StorageKey.USER_INFO),
        storage.get<string[]>(StorageKey.PERMISSIONS),
        storage.get<string[]>(StorageKey.ROLES),
        storage.get<number>(StorageKey.TOKEN_EXPIRE_TIME)
      ])
      
      if (storedToken) setToken(storedToken)
      if (storedRefreshToken) setRefreshToken(storedRefreshToken)
      if (storedUserInfo) setUserInfo(storedUserInfo)
      if (storedPermissions) setPermissions(storedPermissions)
      if (storedRoles) setRoles(storedRoles)
      if (storedExpireTime) setTokenExpireTime(storedExpireTime)
    } else {
      // 从会话存储恢复
      const sessionToken = await storage.getSession<string>(StorageKey.TOKEN)
      const sessionRefreshToken = await storage.getSession<string>(StorageKey.REFRESH_TOKEN)
      
      if (sessionToken) setToken(sessionToken)
      if (sessionRefreshToken) setRefreshToken(sessionRefreshToken)
    }
  }

  // 清理认证状态
  const clearAuthState = async (): Promise<void> => {
    // 停止定时器
    stopTokenRefreshTimer()
    
    // 清理内存状态
    setToken(null)
    setRefreshToken(null)
    setTokenExpireTime(null)
    setUserInfo(null)
    setPermissions([])
    setRoles([])
    
    // 清理存储
    await storage.clear()
  }

  // 获取登录错误信息
  const getLoginErrorMessage = (error: HttpError): string => {
    const codeMessages: Record<number, string> = {
      1001: '用户名或密码错误',
      1002: '账号已被禁用',
      1003: '账号已被锁定',
      1004: '验证码错误',
      1005: '登录失败次数过多，请稍后再试'
    }
    
    return codeMessages[error.code || 0] || error.message || '登录失败'
  }

  // 监听状态变化
  watch(isTokenNearExpiry, (nearExpiry) => {
    if (nearExpiry && refreshToken.value && !isRefreshing.value) {
      refreshAccessToken().catch(console.error)
    }
  })

  // 导出 getters（为了兼容性）
  const getters = {
    getToken: () => token.value,
    getRefreshToken: () => refreshToken.value,
    getUserInfo: () => userInfo.value,
    getPermissions: () => permissions.value,
    getRoles: () => roles.value,
    getIsLoggedIn: () => isLoggedIn.value
  }

  return {
    // 状态
    token: computed(() => token.value),
    refreshToken: computed(() => refreshToken.value),
    tokenExpireTime: computed(() => tokenExpireTime.value),
    userInfo: computed(() => userInfo.value),
    permissions: computed(() => permissions.value),
    roles: computed(() => roles.value),
    rememberMe: computed(() => rememberMe.value),
    
    // 计算属性
    isLoggedIn,
    isTokenExpired,
    isTokenNearExpiry,
    hasPermission,
    hasRole,
    hasAnyPermission,
    hasAllPermissions,
    
    // 方法
    initialize,
    login,
    mobileLogin,
    logout,
    refreshAccessToken,
    fetchUserInfo,
    updateUserInfo,
    
    // 兼容性
    getters,
    
    // 内部方法（仅供测试使用）
    __internal__: {
      setToken,
      setUserInfo,
      clearAuthState
    }
  }
})

// 类型导出
export type AuthStore = ReturnType<typeof useAuthStore> 